package de.preamp.clients.java.player.ui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import de.preamp.clients.java.data.Track;
import de.preamp.clients.java.player.PlaybackListener;
import de.preamp.clients.java.player.PreampPlayerEvent;
import de.preamp.clients.java.player.PreampPlayerException;
import de.preamp.clients.java.utils.ImageLoader;

/**
 * The UI Component for controling the playback.
 * 
 * @author André Stannek
 * @version 2011-06-11
 */
public class ControlsUI extends JPanel implements PlaybackListener // NOPMD
{

    /**
     * Genrated UID.
     */
    private static final long serialVersionUID = 3445679712463352568L;

    /**
     * 
     */
    private final transient JButton play, prev, next, stop;

    /**
     * 
     */
    private final transient JSlider slider;

    /**
     * 
     */
    private final transient JLabel status;

    /**
     * 
     */
    private ControlsBean bean = new ControlsBean();

    /**
     * 
     */
    private transient int position;

    /**
     * 
     */
    public ControlsUI()
    {
	super();
	position = 0;

	play = new JButton();
	prev = new JButton();
	next = new JButton();
	stop = new JButton();

	slider = new JSlider();

	status = new JLabel(" ");

	final ApplicationContext context =
		new FileSystemXmlApplicationContext(
			"src/main/resources/META-INF/applicationContext.xml");
	bean = (ControlsBean) context.getBean("controlsBean");

	bean.getControls().addPlaybackListener(this);

	initUI();
    }

    /**
     * 
     */
    private void initUI() // NOPMD
    {
	final JPanel buttons = new JPanel(new FlowLayout());
	play.setIcon(new ImageIcon(ImageLoader
		.getImageURL("media-playback-start.png")));
	play.addActionListener(new ActionListener()
	{
	    @Override
	    public void actionPerformed(final ActionEvent event)
	    {
		try
		{
		    bean.getControls().playPauseToggle();
		}
		catch (final UnsupportedAudioFileException e)
		{
		    JOptionPane
			    .showMessageDialog(
				    null,
				    "The file you tried to open has an unsupported audio format",
				    "UnsupportedAudioFileException",
				    JOptionPane.ERROR_MESSAGE);
		}
		catch (final IOException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "An I/O-Error occurred", "IOException",
			    JOptionPane.ERROR_MESSAGE);
		}
		catch (final LineUnavailableException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "The audio output line was not available",
			    "LineUnavailableException",
			    JOptionPane.ERROR_MESSAGE);
		}
		catch (final PreampPlayerException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "Playback failed for unknown reason",
			    "PreampPlayerException", JOptionPane.ERROR_MESSAGE);
		}
	    }
	});
	prev.setIcon(new ImageIcon(ImageLoader
		.getImageURL("media-skip-backward.png")));
	prev.addActionListener(new ActionListener()
	{
	    @Override
	    public void actionPerformed(final ActionEvent event)
	    {
		try
		{
		    bean.getControls().previous();
		}
		catch (final UnsupportedAudioFileException e)
		{
		    JOptionPane
			    .showMessageDialog(
				    null,
				    "The file you tried to open has an unsupported audio format",
				    "UnsupportedAudioFileException",
				    JOptionPane.ERROR_MESSAGE);
		}
		catch (final IOException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "An I/O-Error occurred", "IOException",
			    JOptionPane.ERROR_MESSAGE);
		}
		catch (final LineUnavailableException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "The audio output line was not available",
			    "LineUnavailableException",
			    JOptionPane.ERROR_MESSAGE);
		}
		catch (final PreampPlayerException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "Playback failed for unknown reason",
			    "PreampPlayerException", JOptionPane.ERROR_MESSAGE);
		}
	    }
	});
	next.setIcon(new ImageIcon(ImageLoader
		.getImageURL("media-skip-forward.png")));
	next.addActionListener(new ActionListener()
	{
	    @Override
	    public void actionPerformed(final ActionEvent event)
	    {
		try
		{
		    bean.getControls().next();
		}
		catch (final UnsupportedAudioFileException e)
		{
		    JOptionPane
			    .showMessageDialog(
				    null,
				    "The file you tried to open has an unsupported audio format",
				    "UnsupportedAudioFileException",
				    JOptionPane.ERROR_MESSAGE);
		}
		catch (final IOException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "An I/O-Error occurred", "IOException",
			    JOptionPane.ERROR_MESSAGE);
		}
		catch (final LineUnavailableException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "The audio output line was not available",
			    "LineUnavailableException",
			    JOptionPane.ERROR_MESSAGE);
		}
		catch (final PreampPlayerException e)
		{
		    JOptionPane.showMessageDialog(null,
			    "Playback failed for unknown reason",
			    "PreampPlayerException", JOptionPane.ERROR_MESSAGE);
		}
	    }
	});
	stop.setIcon(new ImageIcon(ImageLoader
		.getImageURL("media-playback-stop.png")));
	stop.addActionListener(new ActionListener()
	{
	    @Override
	    public void actionPerformed(final ActionEvent event)
	    {
		bean.getControls().stop();
	    }
	});

	buttons.add(prev);
	buttons.add(stop);
	buttons.add(play);
	buttons.add(next);

	slider.setValue(position);
	slider.setEnabled(false);
	slider.addChangeListener(new ChangeListener()
	{
	    @Override
	    public void stateChanged(final ChangeEvent event)
	    {
		final JSlider source = (JSlider) event.getSource();
		if (!source.getValueIsAdjusting())
		{ // NOPMD
		  // final int skip = source.getValue() - position;
		  // player.seek(skip);
		}
	    }
	});

	this.setLayout(new BorderLayout());
	final JPanel south = new JPanel(new BorderLayout());
	south.add(buttons, BorderLayout.NORTH);
	south.add(status, BorderLayout.SOUTH);
	this.add(slider, BorderLayout.NORTH);
	this.add(south, BorderLayout.SOUTH);

    }

    @Override
    public final void progress(final int bytesread, final long microseconds)
    {
	position = (int) microseconds / 1000;
	slider.setValue(position);

    }

    @Override
    public final void stateChanged(final Track track,
	    final PreampPlayerEvent event)
    {
	switch (event.getType())
	{
	case PLAYING:
	    status.setText("Playing " + track.toString());
	    // slider.setEnabled(true);
	    break;
	case OPENING:
	    status.setText("Opening " + track.toString());
	    break;
	case OPENED:
	    play.setIcon(new ImageIcon(ImageLoader
		    .getImageURL("media-playback-pause.png")));
	    status.setText("Opened " + track.toString());
	    slider.setMaximum(track.getLength());
	    position = 0;
	    slider.setValue(position);
	    // slider.setEnabled(true);
	    break;
	case PAUSED:
	    play.setIcon(new ImageIcon(ImageLoader
		    .getImageURL("media-playback-start.png")));
	    status.setText("Paused " + track.toString());
	    // slider.setEnabled(true);
	    break;
	case RESUMED:
	    play.setIcon(new ImageIcon(ImageLoader
		    .getImageURL("media-playback-pause.png")));
	    status.setText("Playing " + track.toString());
	    // slider.setEnabled(true);
	    break;
	case STOPPED:
	    play.setIcon(new ImageIcon(ImageLoader
		    .getImageURL("media-playback-start.png")));
	    status.setText("");
	    position = 0;
	    slider.setValue(position);
	    slider.setEnabled(false);
	    break;
	case EOM:
	    break;
	default:
	    break;
	}

    }

    @Override
    public final void exceptionOccured(final Exception exception)
    {
	JOptionPane.showMessageDialog(this, "an Exception occured:\n"
		+ exception.getLocalizedMessage(), "Exception",
		JOptionPane.ERROR_MESSAGE);
    }
}
